package com.magic.potato.feign.config;

import com.magic.potato.feign.annotation.FeignClient;
import feign.Client;
import feign.Feign;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.codec.ErrorDecoder;
import feign.jackson.JacksonEncoder;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;

/**
 * @author ycl
 */
@Configuration
public class FeignBeanFactory implements InstantiationAwareBeanPostProcessor {

    private Environment environment;

    private Client client;

    private Decoder decoder;

    private Encoder encoder;

    private ErrorDecoder errorDecoder;

    /**
     * 填充全局配置
     *
     * @param environment
     * @param clients
     * @param decoders
     * @param encoders
     */
    public FeignBeanFactory(Environment environment,
                            ObjectProvider<Client> clients,
                            ObjectProvider<Decoder> decoders,
                            ObjectProvider<Encoder> encoders,
                            ObjectProvider<ErrorDecoder> errorDecoder) {
        this.environment = environment;
        // 设置客户端
        this.client = clients.getIfAvailable(() -> new Client.Default(null, null));
        // 设置解码器
        this.decoder = decoders.getIfAvailable(Decoder.Default::new);
        // 编码器
        this.encoder = encoders.getIfAvailable(JacksonEncoder::new);
        this.errorDecoder = errorDecoder.getIfAvailable(ErrorDecoder.Default::new);
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        FeignClient feignClient = beanClass.getAnnotation(FeignClient.class);
        if (feignClient != null) {
            if (!StringUtils.hasLength(feignClient.value())) {
                throw new RuntimeException(beanClass + "没有指定host地址");
            }
            // 找到feign客户端接口
            return Feign.builder()
                    .client(client)
                    .decoder(decoder)
                    .encoder(encoder)
                    .errorDecoder(errorDecoder)
                    .target(beanClass, environment.resolveRequiredPlaceholders(feignClient.value()));
        }
        return null;
    }
}
